home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / src / adoc_src.lha / adoc-0.17 / gencode.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  15.6 KB  |  720 lines

  1. /*                                                               -*- C -*-
  2.  *  GENCODE.C
  3.  *
  4.  *  (c)Copyright 1995 by Tobias Ferber,  All Rights Reserved.
  5.  *
  6.  *  This file is part of ADOC.
  7.  *
  8.  *  ADOC is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published
  10.  *  by the Free Software Foundation; either version 1 of the License,
  11.  *  or (at your option) any later version.
  12.  *
  13.  *  ADOC is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. /* $VER: $Id: gencode.c,v 1.10 1995/03/20 18:44:19 tf Exp $ */
  24.  
  25. #include <ctype.h>
  26. #include <string.h>
  27. #include <stdlib.h>
  28. #include <stdarg.h>
  29. #include <stdio.h>
  30.  
  31. #include "libfun.h"
  32. #include "adoc.h"
  33.  
  34.  
  35. /* convert tabs in `s' to spaces with a tab step of `ts' */
  36.  
  37. static void fexpand(FILE *fp, int ts, char *s)
  38. {
  39.   int column= 0;
  40.  
  41.   while(*s)
  42.   {
  43.     switch(*s)
  44.     {
  45.       case '\n':
  46.         fputc(*s,fp);
  47.         column= 0;
  48.         break;
  49.  
  50.       case '\t':
  51.         do { fputc(' ',fp); } while( (++column) % ts);
  52.         break;
  53.  
  54.      default:
  55.        fputc(*s,fp);
  56.        ++column;
  57.        break;
  58.     }
  59.     ++s;
  60.   }
  61. }
  62.  
  63.  
  64. /*
  65. **  AUTODOCS
  66. */
  67.  
  68. int gen_autodoc_toc(FILE *fp)
  69. {
  70.   char *fun;
  71.  
  72.   fprintf(fp,"TABLE OF CONTENTS\n\n");
  73.  
  74.   for(fun= stepfun(0); fun; fun= stepfun(1))
  75.     fprintf(fp,"%s\n",fun);
  76.  
  77.   return 0;
  78. }
  79.  
  80.  
  81. int gen_autodoc(FILE *fp, int cols, int tabsize, int flags, char **body_macros)
  82. {
  83.   int err= 0;
  84.  
  85.   char *fun, *sec, *text;
  86.  
  87.   for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  88.   {
  89.     if(flags & ADOC_FORM_FEEDS)
  90.       fputc('\f',fp);
  91.  
  92.     fprintf(fp,"%s%*s\n\n",fun,(int)(cols-strlen(fun)),fun);
  93.  
  94.     for(sec= stepsec(0); sec && (err==0); sec= stepsec(1))
  95.     {
  96.       /* indent the section heading with 3 spaces */
  97.       fprintf(fp,"   %s\n",sec);
  98.  
  99.       if( (text= getsec(sec)) )
  100.       {
  101.         if(text && *text)
  102.         {
  103.           char *x= strexpand(text, body_macros);
  104.  
  105.           if(x)
  106.           {
  107.             if(tabsize > 0)
  108.               fexpand(fp,tabsize,x);
  109.  
  110.             else
  111.               fputs(x,fp);
  112.  
  113.             free(x);
  114.           }
  115.           else err= __LINE__;
  116.         }
  117.  
  118.         fputc('\n',fp);
  119.       }
  120.     }
  121.   }
  122.  
  123.   return err;
  124. }
  125.  
  126.  
  127. /*
  128. **  TEXINFO
  129. */
  130.  
  131.  
  132. /* split `fun' into `chapter' and `section'.
  133.    the string returned by this function has to be disposed via free() by the caller */
  134.  
  135. static char *chapsec(char *fun, char **chapter, char **section)
  136. {
  137.   char *c= strdup(fun);
  138.   char *s= (char *)0;
  139.  
  140.   if(c)
  141.   {
  142.     if( (s= strchr(c,'/')) )
  143.       *s++= '\0';
  144.   }
  145.  
  146.   *chapter= c;
  147.   *section= s;
  148.  
  149.   return c;
  150. }
  151.  
  152. /*
  153.  *  The implementation of references in Texinfo perfectly silly :'(
  154.  *  Instead of offering one simple reference macro, Texinfo comes up
  155.  *  with context-sensitive @ref{}, @xref{}, @pref{}, ... and prints
  156.  *  a `See ...' and `See also ...' right in front of the it...
  157.  */
  158.  
  159. static int see_also(FILE *fp, char *refs, int flags)
  160. {
  161.   int err= 0;
  162.   char *buf= strdup(refs);
  163.  
  164. #define isref(c) ( ('A'<=(c) && (c)<='Z') || \
  165.                    ('a'<=(c) && (c)<='z') || \
  166.                    ('0'<=(c) && (c)<='9') || ((c)=='_') || ((c)=='-') || ((c)=='/') || ((c)=='.') )
  167.  
  168.   if(buf)
  169.   {
  170.     /* make `s' the working pointer in `buf' */
  171.     char *s= buf;
  172.  
  173.     /*
  174.      *  former revisions of ADOC used to indent the parsed references
  175.      *  by the same amount of white space as the first.  Actually we
  176.      *  do not indent them amymore, so out it goes....
  177.      */
  178.  
  179.     /* indentation string of the first reference */
  180. #if 0
  181.     char *indent= (char *)0;
  182. #endif
  183.  
  184.     int num_refs= 0;
  185.  
  186.     while( *s && (err==0) )
  187.     {
  188.       char *l, *r;
  189.  
  190.       /* move `l' and `r' to the left and right end of a reference in `s' */
  191.  
  192.       for(l=s; *l && !isref(*l); l++) ;
  193.       for(r=l; *r &&  isref(*r); r++) ;
  194.  
  195.       /* terminate the reference string with a '\0' */
  196.       if(*r) *r++= '\0';
  197.  
  198.       /* save the indentation of the first reference */
  199. #if 0
  200.       if(num_refs == 0)
  201.       {
  202.         if( (indent= strdup(s)) )
  203.         {
  204.           char *t= indent;
  205.  
  206.           while(*t==' ' || *t=='\t')
  207.             ++t;
  208.  
  209.           *t= '\0';
  210.         }
  211.         else err= __LINE__;
  212.       }
  213. #endif
  214.  
  215.       /* move `s' behind the reference */
  216.       s= r;
  217.  
  218.       if( *l && (err==0) )
  219.       {
  220.         /* look for a function `l' and initialize `fun' to it's name */
  221.         char *fun= (char *)0;
  222.  
  223. /*fprintf(stderr,"--> @ref{%s} ?\n",l);*/
  224.  
  225.         if( getfun(l) )
  226.           fun= strdup(l);
  227.  
  228.         else if( !strchr(l,'/') )
  229.         {
  230.           /*
  231.            *  Okay, we tried it the easy way but perhaps this is a reference
  232.            *  into the library without the library name in front of it.
  233.            *  Let's try appending `l' to the the current library name...
  234.            */
  235.  
  236.           char *f= getfun( (char *)0 );
  237.  
  238.           if(f)
  239.           {
  240.             char *x, *xl, *xr;
  241.  
  242.             if( (x= chapsec(f, &xl, &xr)) )
  243.             {
  244.               size_t len= strlen(xl) + 1 + strlen(l) + 1;
  245.               char *y= (char *)malloc( len * sizeof(char) );
  246.  
  247.               if(y)
  248.               {
  249.                 sprintf(y,"%s/%s",xl,l);
  250.  
  251. /*fprintf(stderr,"--> @ref{%s} ?\n",y);*/
  252.  
  253.                 if( getfun(y) )
  254.                   fun= strdup(y);
  255.  
  256.                 free(y);
  257.               }
  258.               else err= __LINE__;
  259.  
  260.               free(x);
  261.             }
  262.             else err= __LINE__;
  263.           }
  264.           else /* no current function? */
  265.             err= __LINE__;
  266.         }
  267.  
  268.         if(err == 0)
  269.         {
  270.           /* print the reference */
  271.  
  272.           if( fun )
  273.           {
  274.             char *cs, *chapter, *section;
  275.  
  276.             if( (cs= chapsec(fun, &chapter, §ion)) )
  277.             {
  278.               if(flags & TEXI_ITEMIZE_REFERENCES)
  279.               {
  280.                 if(num_refs==0)
  281.                   fprintf(fp,"@itemize\n");
  282.  
  283.                 fprintf(fp,"@item\n@xref{%s %s}.\n",chapter,section);
  284.               }
  285.               else /* not itemized */
  286.               {
  287.                 if( (num_refs==0) && (flags & TEXI_GROUP_SECTIONS) )
  288.                   fprintf(fp,"@group\n");
  289.  
  290.                 fprintf(fp,"%s{%s %s},\n", (num_refs==0) ? "@*@xref"
  291.                                                          : "@ref"
  292.                                          , chapter
  293.                                          , section
  294.                 );
  295.               }
  296.  
  297.               free(cs);
  298.             }
  299.             else err= __LINE__;
  300.  
  301.             free(fun);
  302.           }
  303.           else /* !fun */
  304.           {
  305.             if(flags & TEXI_ITEMIZE_REFERENCES)
  306.             {
  307.               if(num_refs==0)
  308.                 fprintf(fp,"@itemize\n");
  309.  
  310.               fprintf(fp,"@item\nSee @file{%s}\n",l);
  311.             }
  312.             else /* not itemized */
  313.             {
  314.               if( (num_refs==0) && (flags & TEXI_GROUP_SECTIONS) )
  315.                 fprintf(fp,"@group\n");
  316.  
  317.               fprintf(fp,"%s{%s},\n",((num_refs==0) ? "@*See @file":"@file"),l);
  318.             }
  319.           }
  320.  
  321.           /* now at least one reference is printed */
  322.           ++num_refs;
  323.         }
  324.       }
  325.     }
  326.  
  327.     if(num_refs > 0)
  328.     {
  329.       if(flags & TEXI_ITEMIZE_REFERENCES)
  330.         fprintf(fp,"@end itemize\n");
  331.  
  332.       else /* not itemized */
  333.       {
  334.         if(flags & TEXI_GROUP_SECTIONS)
  335.           fprintf(fp,"@end group\n");
  336.  
  337.         fprintf(fp,"for more information.\n");
  338.       }
  339.     }
  340.  
  341. #if 0
  342.     if(indent)
  343.       free(indent);
  344. #endif
  345.  
  346.     free(buf);
  347.   }
  348.   else err= __LINE__;
  349.  
  350. #undef isref
  351.  
  352.   return err;
  353. }
  354.  
  355.  
  356. int gen_texinfo_header(FILE *fp, char *fname, char **header_macros)
  357. {
  358.   int err= 0;
  359.  
  360.   char *default_header=
  361.     "\\input texinfo  @c -*-texinfo-*-\n"
  362.     "@comment %%**start of header\n"
  363.     "@setfilename PROJECT.guide\n"
  364.     "@settitle Autodocs for @code{PROJECT}\n"
  365.     "@paragraphindent 0\n"
  366.     "@iftex\n"
  367.     "@afourpaper\n"
  368.     "@headings double\n"
  369.     "@finalout\n"
  370.     "@setchapternewpage on\n"  /* odd */
  371.     "@end iftex\n"
  372.     "@comment %%**end of header\n\n"
  373.     "@ifinfo\n"
  374.     "@node Top\n"
  375.     "@top\n"
  376.     "This document describes @code{PROJECT} version EDITION.\n\n"  /* was @value{EDITION} */
  377.     "@noindent Copyright @copyright{} COPYRIGHT\n"
  378.     "@end ifinfo\n\n"
  379.     "@titlepage\n"
  380.     "@title PROJECT\n"
  381.     "@subtitle Documentation taken from source code\n"
  382.     "@subtitle Edition for Version EDITION\n"
  383.     "@subtitle @today\n"
  384.     "@author AUTHOR\n\n"
  385.     "@page\n"
  386.     "@vskip 0pt plus 1filll\n"
  387.     "Copyright @copyright{} COPYRIGHT\n"
  388.     "@end titlepage\n\n";
  389.  
  390.   if(fname && *fname)
  391.   {
  392.     FILE *fh= fopen(fname,"r");
  393.  
  394.     if(fh)
  395.     {
  396.       char *header= (char *)0;
  397.       size_t header_size= 0;
  398.  
  399.       /* compute the size of the header file */
  400.  
  401. #ifdef BUGGY_FTELL
  402.  
  403.       do {
  404.  
  405.         (void)fgetc(fh);
  406.  
  407.         if(!feof(fh))
  408.           ++header_size;
  409.  
  410.       } while(!feof(fh) || ferror(fh))
  411.  
  412. #else /* ftell() works fine */
  413.  
  414.       if( fseek(fh,0L,2L) >= 0) /* 2 == OFFSET_END */
  415.         header_size= ftell(fh);
  416.  
  417.       else
  418.         err= __LINE__;
  419.  
  420. #endif /* BUGGY_FTELL */
  421.  
  422.       if(!ferror(fh) && header_size > 0)
  423.       {
  424.         if(fseek(fh,-header_size,1L) < 0) /* 1 == OFFSET_CURRENT */
  425.           err= __LINE__;
  426.       }
  427.       else err= __LINE__;
  428.  
  429.  
  430.       /* load the header */
  431.  
  432.       if(err == 0)
  433.       {
  434.         if( (header= (char *)malloc( (header_size + 1) * sizeof(char) )) )
  435.         {
  436.           fread(header, sizeof(char), header_size, fh);
  437.           header[header_size]= '\0';
  438.  
  439.           if( ferror(fh) )
  440.           {
  441.             free(header);
  442.             header= (char *)0;
  443.             err= __LINE__;
  444.           }
  445.         }
  446.         else err= __LINE__;
  447.       }
  448.  
  449.       if(err == 0)
  450.       {
  451.         char *x= strexpand(header, header_macros);
  452.  
  453.         if(x)
  454.         {
  455.           fputs(x,fp);
  456.           free(x);
  457.         }
  458.         else /* out of memory */
  459.           err= __LINE__;
  460.       }
  461.  
  462.       fclose(fh);
  463.     }
  464.   }
  465.  
  466.   else /* !fname */
  467.   {
  468.     char *x= strexpand(default_header, header_macros);
  469.  
  470.     if(x)
  471.     {
  472.       fputs(x,fp);
  473.       free(x);
  474.     }
  475.     else /* out of memory */
  476.       err= __LINE__;
  477.   }
  478.  
  479.   return err;
  480. }
  481.  
  482.  
  483.  
  484. int gen_texinfo(FILE *fp, int tabsize, int flags, char *body_environment, char **body_macros)
  485. {
  486.   int err= 0;
  487.   char *fun, *sec;
  488.  
  489.   /* main menu:
  490.      create a @menu with an entry for each library.
  491.      an additional entry will be created for the function index */
  492.  
  493.   if(err == 0)
  494.   {
  495.     char *last_chapter = (char *)0;  /* last printed chapter */
  496.     char *last_cs      = (char *)0;  /* string allocated for `last_chapter' */
  497.  
  498.     fprintf(fp,"@menu\n");
  499.  
  500.     for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  501.     {
  502.       char *cs, *chapter, *section;
  503.  
  504.       if( (cs= chapsec(fun, &chapter, §ion)) )
  505.       {
  506.         if( !last_chapter || strcmp(last_chapter, chapter) )
  507.         {
  508.           fprintf(fp,"* %s::\n", chapter);
  509.  
  510.           if(last_cs)
  511.             free(last_cs);
  512.  
  513.           last_cs      = cs;
  514.           last_chapter = chapter;
  515.         }
  516.         else
  517.           free(cs);
  518.       }
  519.       else /* out of memory */
  520.         err= __LINE__;
  521.     }
  522.  
  523.     if(last_cs)
  524.       free(last_cs);
  525.  
  526.     fprintf(fp, "\n"
  527.                 "* Function Index::\n"
  528.                 "@end menu\n\n");
  529.   }
  530.  
  531. #if 0
  532.  
  533.   /* create one single (flat) menu for functions mapped to
  534.      @chapters.  This code is obsolete since we introduced
  535.      the hierarchical layout with libraries mapped to
  536.      @chapters and functions mapped to @sections. */
  537.  
  538.   if(err == 0)
  539.   {
  540.     fprintf(fp,"@menu\n");
  541.  
  542.     for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  543.     {
  544.       char *cs, *chapter, *section;
  545.  
  546.       if( (cs= chapsec(fun, &chapter, §ion)) )
  547.       {
  548.         fprintf(fp,"* %s %s::\n", chapter, section);
  549.         free(cs);
  550.       }
  551.       else /* out of memory */
  552.         err= __LINE__;
  553.     }
  554.  
  555.     fprintf(fp, "\n"
  556.                 "* Function Index::\n"
  557.                 "@end menu\n\n");
  558.   }
  559.  
  560. #endif
  561.  
  562.   /* chapters & sections */
  563.  
  564.   if(err == 0)
  565.   {
  566.     char *last_chapter = (char *)0;
  567.     char *last_cs      = (char *)0;
  568.  
  569.     for(fun= stepfun(0); fun && (err==0); fun= stepfun(1))
  570.     {
  571.       char *cs, *chapter, *section;
  572.  
  573.       if( (cs= chapsec(fun, &chapter, §ion)) )
  574.       {
  575.         if( !last_chapter || strcmp(last_chapter, chapter) )
  576.         {
  577.           /*
  578.            *  Start a new library
  579.            */
  580.  
  581.           fprintf(fp, "\n"
  582.                       "@node %s\n"
  583.                       "@chapter %s\n\n"
  584.                       ,chapter
  585.                       ,chapter
  586.           );
  587.  
  588.           /* print a sub menu for the current chapter */
  589.  
  590.           pushfun();
  591.           {
  592.             int done;
  593.             char *sub_fun;
  594.  
  595.             fprintf(fp,"@menu\n");
  596.             for(sub_fun= fun, done= 0; sub_fun && (err==0) && !done; sub_fun= stepfun(1))
  597.             {
  598.               char *sub_cs, *sub_chapter, *sub_section;
  599.  
  600.               if( (sub_cs= chapsec(sub_fun, &sub_chapter, &sub_section)) )
  601.               {
  602.                 if( (done= strcmp(sub_chapter, chapter)) == 0 )
  603.                   fprintf(fp,"* %s %s::\n", sub_chapter, sub_section);
  604.  
  605.                 free(sub_cs);
  606.               }
  607.               else err= __LINE__;
  608.             }
  609.             fprintf(fp,"@end menu\n\n");
  610.           }
  611.           popfun();
  612.  
  613.           if(last_cs)
  614.             free(last_cs);
  615.  
  616.           last_cs      = cs;
  617.           last_chapter = chapter;
  618.         }
  619.  
  620.         else /* we didn't start a new page for the chapter */
  621.         {
  622.           if(flags & TEXI_FUNCTION_NEWPAGE)
  623.             fprintf(fp,"@page\n");
  624.         }
  625.  
  626.         /*
  627.          *  Begin a new function 
  628.          */
  629.  
  630.         fprintf(fp, "\n"
  631.                     "@node %s %s\n"
  632.                     "@section %s\n"
  633.                     "@findex %s\n"
  634.                     "\n"
  635.                     ,chapter, section
  636.                     ,section
  637.                     ,section
  638.         );
  639.  
  640.         if(flags & TEXI_TABLE_FUNCTIONS)
  641.           fprintf(fp,"@table @b\n");
  642.  
  643.         for(sec= stepsec(0); sec && (err == 0); sec= stepsec(1))
  644.         {
  645.           char *text= getsec(sec);
  646.  
  647.           if(text && *text)
  648.           {
  649.  
  650.             if(flags & TEXI_TABLE_FUNCTIONS)
  651.               fprintf(fp,"@item %s\n",sec);
  652.             else
  653.              fprintf(fp,"@b{%s}\n",sec);  /* was @strong{} or @code{} */
  654.              /*fprintf(fp,"@noindent\n@b{%s}\n",sec);*/
  655.  
  656.  
  657.             if( (flags & TEXI_PARSE_REFERENCES) && strcmp(sec,"SEE ALSO") == 0 )
  658.               err= see_also(fp, text, flags);
  659.  
  660.             else /* ! "SEE ALSO" */
  661.             {
  662.               char *x= strexpand(text,body_macros);
  663.  
  664.               if(x)
  665.               {
  666.                 fprintf(fp,"@noindent\n"
  667.                            "@%s\n",body_environment);
  668.  
  669.                 if(flags & TEXI_GROUP_SECTIONS)
  670.                   fprintf(fp,"@group\n");
  671.  
  672.                 if(tabsize > 0)
  673.                   fexpand(fp,tabsize,x);
  674.                 else
  675.                   fputs(x,fp);
  676.  
  677.                 if(flags & TEXI_GROUP_SECTIONS)
  678.                   fprintf(fp,"@end group\n");
  679.  
  680.                 fprintf(fp,"@end %s\n"
  681.                            "@refill\n",body_environment);
  682.  
  683.                 free(x);
  684.               }
  685.               else /* out of memory */
  686.                 err= __LINE__;
  687.             }
  688.           }
  689.           /* else (!text) -> no error */
  690.  
  691.           fprintf(fp,"\n");
  692.         }
  693.  
  694.         if(flags & TEXI_TABLE_FUNCTIONS)
  695.           fprintf(fp,"@end table\n");
  696.       }
  697.       else /* out of memory */
  698.         err= __LINE__;
  699.     }
  700.  
  701.     if(last_cs)
  702.       free(last_cs);
  703.   }
  704.  
  705.   /* index */
  706.  
  707.   if(err == 0)
  708.   {
  709.     fprintf(fp, "@node Function Index\n"
  710.                 "@unnumbered Function Index\n"
  711.                 "@printindex fn\n"
  712.                 "\n"
  713.                 "@page\n"
  714.                 "@contents\n"
  715.                 "@bye\n");
  716.   }
  717.  
  718.   return err;
  719. }
  720.